package com.koko.service.Impl;

import com.koko.constant.MessageConstant;
import com.koko.context.BaseContext;
import com.koko.exception.OrderPaymentRepeatException;
import com.koko.exception.UserAlreadyHavaTheGameException;
import com.koko.feign.GameFeignService;
import com.koko.feign.UserFeignService;
import com.koko.game.entity.GameDetail;
import com.koko.game.entity.GamePrice;
import com.koko.game.vo.GameCartVO;
import com.koko.mapper.OrderGameMapper;
import com.koko.mapper.OrderMapper;
import com.koko.order.dto.OrderGameDTO;
import com.koko.order.dto.PayDTO;
import com.koko.order.entity.Order;
import com.koko.order.entity.OrderGame;
import com.koko.order.vo.OrderGameVO;
import com.koko.order.vo.OrderVO;
import com.koko.properties.KokoNameProperties;
import com.koko.properties.RabbitmqProperties;
import com.koko.result.Result;
import com.koko.service.OrderService;
import com.koko.user.vo.UserVO;
import com.koko.utils.UniqueNumberGeneratorUtil;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class OrderServiceImpl implements OrderService {
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private OrderGameMapper orderGameMapper;
    @Autowired
    private GameFeignService gameFeignService;
    @Autowired
    private UserFeignService userFeignService;
    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Override
    @Transactional
    public void addOrder(List<OrderGameDTO> orderDTO) {
        Order order = new Order();
        order.setAmount(new BigDecimal(0));
        List<OrderGame> orderGames = new ArrayList<>();
        for (OrderGameDTO gameDTO : orderDTO) {
            String userNickname = userFeignService.isUserHaveGame(
                    gameDTO.getReceiveId() != null ? gameDTO.getReceiveId() : BaseContext.getCurrentId(),
                    gameDTO.getGameId());
            // 判断用户是否拥有此游戏
            if (userNickname != null) {
                String message = userNickname.replace("\"", "") + MessageConstant.ALREADY_HAVE_THE_GAME;
                throw new UserAlreadyHavaTheGameException(message);
            }
            // 1. 通过gameId获取游戏信息
            Result<GameCartVO> result = gameFeignService.getGameOnCartByGameId(gameDTO.getGameId());
            GameCartVO gameCart = result.getData();
            // 1.1 计算总价
            order.setAmount(order.getAmount().add(result.getData().getGamePrice().getCurrentPrice()));
            // 2. 将查询到的游戏暂存到list列表中
            // 2.1 封装订单游戏对象
            OrderGame orderGame = OrderGame.builder()
                    .gameId(gameDTO.getGameId())
                    .chineseName(gameCart.getChineseName())
                    .englishName(gameCart.getEnglishName())
                    .receiveId(gameDTO.getReceiveId() != null ? gameDTO.getReceiveId() : BaseContext.getCurrentId())
                    .originPrice(gameCart.getGamePrice().getOriginPrice())
                    .gameDiscount(gameCart.getGamePrice().getDiscount())
                    .finalPrice(gameCart.getGamePrice().getCurrentPrice())
                    .build();
            // 2.2 添加到list列表中
            orderGames.add(orderGame);
        }
        // 3. 封装订单表
        // 3.1 生成交易单号
        order.setOrderNumber(
                UniqueNumberGeneratorUtil.generateOrderNumber(KokoNameProperties.ORDER_NUMBER_PREFIX)
        );
        // 3.2 获取下单用户id
        order.setUserId(BaseContext.getCurrentId());
        // 3.3 获取下单时间
        order.setOrderTime(LocalDateTime.now());
        // 4. 插入数据库
        // 4.1 判断数据库中是否有未支付订单
        Long id = orderMapper.isUserHaveOrderToPay(BaseContext.getCurrentId());
        if (id != null) {
            // 4.2 有则删除订单
            this.deleteById(id);
            // throw new OrderHadNoPayException(MessageConstant.ORDER_HAD_NO_PAY);
        }
        // 4.3 没有则插入
        orderMapper.insert(order);
        // 5. 继续完善订单游戏表
        for (OrderGame orderGame : orderGames) {
            // 5.1 获取订单id
            orderGame.setOrderId(order.getId());
            // 6. 插入数据库
            orderGameMapper.insert(orderGame);
        }
    }

    /**
     * 查询当前用户是否有订单
     * @return
     */
    @Override
    public Long getOrderId() {
        return orderMapper.isUserHaveOrderToPay(BaseContext.getCurrentId());
    }


    /**
     * 获取订单
     * @return
     */
    @Override
    public OrderVO getOrder() {
        OrderVO orderVO = new OrderVO();
        // 1. 先获取订单数据
        Order order = orderMapper.getUnPayedOrder(BaseContext.getCurrentId());
        BeanUtils.copyProperties(order, orderVO);
        // 2. 获取订单游戏数据
        List<OrderGame> orderGameList = orderGameMapper.getOrderGameListByOrderId(order.getId());
        // 3. 封装响应的订单游戏数据
        List<OrderGameVO> list = orderGameList.stream().map((item) -> {
            OrderGameVO gameVO = new OrderGameVO();
            // 3.1. 查询游戏详细信息
            Result<GameDetail> gameDetailResult = gameFeignService.getGameDetailByGameId(item.getGameId());
            gameVO.setSimplePicture(gameDetailResult.getData().getSimplePicture());
            // 3.2. 查询用户信息
            if (!item.getReceiveId().equals(BaseContext.getCurrentId())) {
                Result<UserVO> userResult = userFeignService.getUserByUserId(item.getReceiveId());
                gameVO.setReceiveUsername(userResult.getData().getUsername());
            }
            gameVO.setId(item.getId());
            gameVO.setChineseName(item.getChineseName());
            gameVO.setCurrentPrice(item.getFinalPrice());
            return gameVO;
        }).collect(Collectors.toList());
        // 4. 封装订单数据
        orderVO.setGames(list);
        return orderVO;
    }

    /**
     * 更具gameId删除订单游戏内容
     * @param id
     */
    @Override
    @Transactional
    public void deleteById(Long id) {
        // 1. 先删除订单表
        orderMapper.deleteById(id);
        // 2. 在删除订单游戏表
        orderGameMapper.deleteByOrderId(id);
    }

    @Override
    @Transactional
    public void deleteByUserId(Long userId) {
        // 1. 先通过userId查找订单数据
        Order order = orderMapper.getByUserId(userId);
        this.deleteById(order.getId());
    }

    /**
     * 支付
     * @param payment
     */
    @Override
    public Result<String> pay(PayDTO payDTO) {
        // 1. 判断支付方式
        // 2. 获取订单信息
        Order order = orderMapper.getByOrderNumber(payDTO.getOrderNumber());
        if (order.getPayment() != null && order.getPayTime() != null) {
            // 订单已支付，无需重复支付
            throw new OrderPaymentRepeatException(MessageConstant.ORDER_PAYMENT_REPEAT);
        }
        if (payDTO.getPayment() == 0) {
            // 2.2 获取支付金额
            BigDecimal toPay = order.getAmount();
            // 3. 将预付款发送给用户模块
            Result<String> result = userFeignService.pay(toPay.toString());
            if (result.getCode() == 0) {
                // 3.1 支付失败
                return Result.error(result.getMsg());
            }
            // 支付成功
            // 4 写入数据库
            order.setPayTime(LocalDateTime.now());
            order.setPayment(0);
            orderMapper.update(order);
        }
        // 5. 通知其他租组件（通过rabbitmq）
        String exchangeName = RabbitmqProperties.PAY_SUCCESS_EXCHANGE;
        // 获取订单信息存入
        order.setOrderTime(null);
        order.setPayTime(null);
        rabbitTemplate.convertAndSend(exchangeName, "", order);
        // 6.1 用户添加游戏
        // 6.2 第三方服务发送邮件
        return Result.success();
    }
}
